home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / WORM.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  7KB  |  265 lines

  1. /*    SCCS Id: @(#)worm.c    3.0    88/11/11
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. #ifdef WORM
  8. #include "wseg.h"
  9.  
  10. static void FDECL(remseg,(struct monst *,struct wseg *));
  11.  
  12. /* Each tailed worm has a wormno.  This is used as an index for the following
  13.  * arrays:
  14.  * wsegs: the start of a a linked list of segments, located at the tail.
  15.  * wheads: the end of a linked list of segments, located at the head.  Putting
  16.  *    the tail of the list at the head of the worm and vice versa is an
  17.  *    endless source of confusion, but necessary.  From now on, we will use
  18.  *    "start" and "end" to refer to the list, and "head" and "tail" to refer
  19.  *    to the worm.
  20.  * wgrowtime: obvious.
  21.  *
  22.  * When a worm is moved, we add a new segment at the head (end of the list)
  23.  * and (unless we want it to grow) delete the segment at the tail (beginning
  24.  * of the list).  This new head segment is located in the same square as
  25.  * the actual head of the worm (thus requiring a special case when setting
  26.  * level.monsters upon worm movement).  If we do want to grow the worm, we
  27.  * don't delete the tail segment, and we give the worm extra hit points,
  28.  * which possibly go into its maximum.
  29.  *
  30.  * Non-moving worms (worm_nomove) shrink instead of grow as their tails keep
  31.  * going while their heads are stopped short.  Delete the tail segment,
  32.  * and remove hit points from the worm.
  33.  */
  34. struct wseg *wsegs[32] = DUMMY, *wheads[32] = DUMMY, *m_atseg = 0;
  35. long wgrowtime[32] = DUMMY;
  36.  
  37. int
  38. getwn(mtmp)
  39. struct monst *mtmp;
  40. {
  41.     register int tmp;
  42.  
  43.     for(tmp = 1; tmp < 32; tmp++)
  44.         if(!wsegs[tmp]) {
  45.         mtmp->wormno = tmp;
  46.         return(1);
  47.         }
  48.     return(0);    /* level infested with worms */
  49. }
  50.  
  51. /* called to initialize a worm unless cut in half */
  52. void
  53. initworm(mtmp)
  54. struct monst *mtmp;
  55. {
  56.     register struct wseg *wtmp;
  57.     register int tmp = mtmp->wormno;
  58.  
  59.     if(!tmp) return;
  60.     wheads[tmp] = wsegs[tmp] = wtmp = newseg();
  61.     wgrowtime[tmp] = 0;
  62.     wtmp->wx = mtmp->mx;
  63.     wtmp->wy = mtmp->my;
  64. /*    wtmp->wdispl = 0; */
  65.     wtmp->nseg = 0;
  66. }
  67.  
  68. static void
  69. remseg(mtmp,wtmp)
  70. struct monst *mtmp;
  71. register struct wseg *wtmp;
  72. {
  73.     if (mtmp->mx != wtmp->wx || mtmp->my != wtmp->wy)
  74.         remove_monster(wtmp->wx, wtmp->wy);
  75.     if(wtmp->wdispl) newsym(wtmp->wx, wtmp->wy);
  76.     free((genericptr_t) wtmp);
  77. }
  78.  
  79. void
  80. worm_move(mtmp)
  81. struct monst *mtmp;
  82. {
  83.     register struct wseg *wtmp, *whd;
  84.     register int tmp = mtmp->wormno;
  85.  
  86.     wtmp = newseg();
  87.     wtmp->wx = mtmp->mx;
  88.     wtmp->wy = mtmp->my;
  89.     wtmp->nseg = 0;
  90. /*    wtmp->wdispl = 0; */
  91.     (whd = wheads[tmp])->nseg = wtmp;
  92.     wheads[tmp] = wtmp;
  93.     if(cansee(whd->wx,whd->wy)){
  94.         unpmon(mtmp);
  95.         atl(whd->wx, whd->wy, S_WORM_TAIL);
  96.         whd->wdispl = 1;
  97.     } else    whd->wdispl = 0;
  98.     if(wgrowtime[tmp] <= moves) {
  99.         if(!wgrowtime[tmp]) wgrowtime[tmp] = moves + rnd(5);
  100.         else wgrowtime[tmp] = wgrowtime[tmp]+2+rnd(15);
  101.         mtmp->mhp += 3;
  102.         if (mtmp->mhp > MHPMAX) mtmp->mhp = MHPMAX;
  103.         if (mtmp->mhp > mtmp->mhpmax) mtmp->mhpmax = mtmp->mhp;
  104.         return;
  105.     }
  106.     whd = wsegs[tmp];
  107.     wsegs[tmp] = whd->nseg;
  108.     remseg(mtmp, whd);
  109. }
  110.  
  111. void
  112. worm_nomove(mtmp)
  113. register struct monst *mtmp;
  114. {
  115.     register int tmp;
  116.     register struct wseg *wtmp;
  117.  
  118.     tmp = mtmp->wormno;
  119.     wtmp = wsegs[tmp];
  120.     if(wtmp == wheads[tmp]) return;
  121.     if(wtmp == 0 || wtmp->nseg == 0) panic("worm_nomove?");
  122.     wsegs[tmp] = wtmp->nseg;
  123.     remseg(mtmp, wtmp);
  124.     if (mtmp->mhp > 3) mtmp->mhp -= 3;    /* mhpmax not changed ! */
  125.     else mtmp->mhp = 1;
  126. }
  127.  
  128. void
  129. wormdead(mtmp)
  130. register struct monst *mtmp;
  131. {
  132.     register int tmp = mtmp->wormno;
  133.     register struct wseg *wtmp, *wtmp2;
  134.  
  135.     if(!tmp) return;
  136.     mtmp->wormno = 0;
  137.     for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
  138.         wtmp2 = wtmp->nseg;
  139.         remseg(mtmp, wtmp);
  140.     }
  141.     wsegs[tmp] = 0;
  142. }
  143.  
  144. void
  145. wormhit(mtmp)
  146. register struct monst *mtmp;
  147. {
  148.     register int tmp = mtmp->wormno;
  149.     register struct wseg *wtmp;
  150.  
  151.     if(!tmp) return;    /* worm without tail */
  152.     for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
  153.         if (dist(wtmp->wx, wtmp->wy) < 3) (void) mattacku(mtmp);
  154. }
  155.  
  156. void
  157. wormsee(tmp)
  158. register unsigned int tmp;
  159. {
  160.     register struct wseg *wtmp = wsegs[tmp];
  161.  
  162.     if(!wtmp) panic("wormsee: wtmp==0");
  163.  
  164.     for(; wtmp->nseg; wtmp = wtmp->nseg)
  165.         if(!cansee(wtmp->wx,wtmp->wy) && wtmp->wdispl) {
  166.             newsym(wtmp->wx, wtmp->wy);
  167.             wtmp->wdispl = 0;
  168.         }
  169.         else if (cansee(wtmp->wx, wtmp->wy) && !wtmp->wdispl) {
  170.             atl(wtmp->wx, wtmp->wy, S_WORM_TAIL);
  171.             wtmp->wdispl = 1;
  172.         }
  173. }
  174.  
  175. void
  176. cutworm(mtmp, x, y, weptyp)
  177. struct monst *mtmp;
  178. xchar x,y;
  179. unsigned weptyp;        /* uwep->otyp or 0 */
  180. {
  181.     register struct wseg *wtmp, *wtmp2;
  182.     struct monst *mtmp2;
  183.     int tmp, tmp2;
  184.  
  185.     if(mtmp->mx == x && mtmp->my == y) return;    /* hit headon */
  186.  
  187.     /* cutting goes best with axe or sword */
  188.     tmp = rnd(20);
  189.     if(weptyp >= SHORT_SWORD && weptyp <= KATANA ||
  190.        weptyp == AXE)
  191.         tmp += 5;
  192.  
  193.     if(tmp < 12) return;
  194.  
  195.     /* if tail then worm just loses a tail segment */
  196.     tmp = mtmp->wormno;
  197.     wtmp = wsegs[tmp];
  198.     if(wtmp->wx == x && wtmp->wy == y){
  199.         wsegs[tmp] = wtmp->nseg;
  200.         remseg(mtmp, wtmp);
  201.         return;
  202.     }
  203.  
  204.     /* cut the worm in two halves */
  205.     mtmp2 = newmonst(0);
  206.     *mtmp2 = *mtmp;
  207.     mtmp2->mxlth = mtmp2->mnamelth = 0;
  208.  
  209.     /* sometimes the tail end dies */
  210.     if(rn2(3) || !getwn(mtmp2)){
  211.         monfree(mtmp2);
  212.         place_worm_seg(mtmp, mtmp2->mx, mtmp2->my);
  213.             /* since mtmp is still on that spot */
  214.         tmp2 = 0;
  215.     } else {
  216.         tmp2 = mtmp2->wormno;
  217.         wsegs[tmp2] = wsegs[tmp];
  218.         wgrowtime[tmp2] = 0;
  219.     }
  220.     /* do-loop: go from the tail to the head.  Segments close to the tail
  221.      * either die or become part of worm 2.  We stop at the hit segment
  222.      * and this loop never goes down the entire length of the worm.
  223.      */
  224.     do {
  225.         /* The segment immediately next to (tailwards) the one hit, */
  226.         /* becoes the head of the new second worm.  Note: at this point, */
  227.         /* wtmp->nseg is the one you hit, wtmp is immediately tailwards, */
  228.         /* and wtmp->nseg->nseg is immediately headwards. */
  229.         if(wtmp->nseg->wx == x && wtmp->nseg->wy == y){
  230.         if(tmp2) wheads[tmp2] = wtmp;
  231.         wsegs[tmp] = wtmp->nseg->nseg;
  232.         remseg(mtmp, wtmp->nseg);
  233.         wtmp->nseg = 0;
  234.         if(tmp2) {
  235.             kludge("You cut %s in half.", mon_nam(mtmp));
  236.         /* devalue the monster level of both halves of the worm */
  237.             mtmp->m_lev = (mtmp->m_lev <= 3) ? 2 : mtmp->m_lev - 2;
  238.             mtmp2->m_lev = mtmp->m_lev;
  239.         /* calculate the mhp on the new (lower) monster level */
  240.             mtmp2->mhpmax = mtmp2->mhp = d((int)mtmp2->m_lev, 8);
  241.             place_monster(mtmp2, wtmp->wx, wtmp->wy);
  242.             mtmp2->nmon = fmon;
  243.             fmon = mtmp2;
  244.             mtmp2->mdispl = 0;
  245.             pmon(mtmp2);
  246.         } else {
  247.             if (Blind) You("cut off part of its tail.");
  248.             else You("cut off part of %s's tail.", mon_nam(mtmp));
  249.             remseg(mtmp, wtmp);
  250.         }
  251.         mtmp->mhp /= 2;
  252.         return;
  253.         }
  254.     /* Worm segments which are closer to the tail than the one you hit, */
  255.     /* get either deleted or transferred from the old to new worms */
  256.         wtmp2 = wtmp->nseg;
  257.         if(!tmp2) remseg(mtmp, wtmp);
  258.         else place_worm_seg(mtmp2, wtmp->wx, wtmp->wy);
  259.         wtmp = wtmp2;
  260.     } while(wtmp->nseg);
  261.     panic("Cannot find worm segment");
  262. }
  263.  
  264. #endif /* WORM /**/
  265.